import Vue,{PropOptions,PropType,VNode} from 'vue';
import {QInnerLoading,QSpinner} from 'quasar';
import Popup from '../popup';
import {PlainObject,preprocessor} from '../../../../types';
import {convertCssLength} from '../../../util/common';
import {rootContainerVue} from '../../js/app/rootContainer';
/**
 * 存储所有弹窗的层级信息
 */
const zIndexs:Array<number>=[0];
/**
 * 弹窗
 * @author 唐国雄
 * @date 2021/7/29
 * 属性----------------------
 * v-model					是否显示, boolean
 * :transition-appear		初始渲染动画, boolean
 * :content-class			内容的class, string
 * :content-style			内容的style, PlainObject
 * :head					是否有标题, boolean
 * :title					标题, string
 * :foot					是否有页脚, boolean
 * :closable				是否有关闭按钮, boolean
 * :confirm-text			确定按钮文字, string
 * :close-text				取消按钮文字, string
 * :before-close			关闭前处理器, 支持返回promise, 返回true表示禁止关闭
 * :loading					加载状态, boolean
 * :loading-confirm			按钮加载状态, boolean
 * 事件----------------------
 * @input				显示状态, boolean
 * @show				开始显示
 * @shown				显示动画完毕
 * @hide				开始隐藏
 * @hidden				隐藏动画完毕
 * @confirm				点击确认
 * @close				点击关闭
 * 插槽----------------------
 * #default				body内容
 * #title				标题
 * #foot				页脚
 * #loading				加载中
 * #loading-but			确定按钮加载中
 */
export default Vue.extend({
	name:'Modal',
	props:{
		//是否显示
		value:Boolean,
		//初始渲染动画
		transitionAppear:Boolean,
		//内容的class
		contentClass:String,
		//内容的style
		contentStyle:{} as PropOptions<PlainObject>,
		//水平最小预留长度
		horizontalGap:{
			type:[Number,String],
			default:50
		},
		//垂直最小预留长度
		verticalGap:{
			type:[Number,String],
			default:50
		},
		//是否有标题
		head:{
			type:Boolean,
			default:true
		},
		//标题
		title:String,
		//是否有页脚
		foot:{
			type:Boolean,
			default:true
		},
		//是否有关闭按钮
		closable:{
			type:Boolean,
			default:true
		},
		//确定按钮文字
		confirmText:{
			type:String,
			default:'确定'
		},
		//取消按钮文字
		closeText:{
			type:String,
			default:'取消'
		},
		//关闭前处理器, 支持返回promise, 返回true表示禁止关闭
		beforeClose:Function as PropType<preprocessor>,
		//加载状态
		loading:Boolean,
		//确定按钮加载状态
		loadingConfirm:Boolean,
	},
	data(){
		return {
			//实际显示状态
			show:this.value,
			//取消按钮加载状态
			loadingClose:false,
			//层级
			zIndex:0,
		};
	},
	computed:{
		classes():string{
			return 'lexmis-Modal';
		},
		realContentStyle():PlainObject{
			return Object.assign({
				maxWidth:`calc(100% - ${convertCssLength(this.horizontalGap)})`,
				maxHeight:`calc(100% - ${convertCssLength(this.verticalGap)})`,
			},this.contentStyle);
		},
	},
	watch:{
		show(val){
			this.$emit('input',val);
		},
		value(val){
			if(val!==this.show){
				this.show=val;
			}
		},
	},
	created(){
		this.$watch('show',function(val){
			if(val){
				this.zIndex=Math.max(...zIndexs)+1;
				zIndexs.push(this.zIndex);
			}else{
				const pos=zIndexs.indexOf(this.zIndex);
				if(pos!==-1){
					zIndexs.splice(pos,1);
				}
			}
		},{immediate:true});
	},
	mounted(){
		if(this.$root.$options.name!=='RootContainer'){
			const dom=rootContainerVue.$el.querySelector('.lexmis-ModalContainer')!;
			dom.append(this.$el);
		}
	},
	methods:{
		confirm(){
			if(!this.loadingConfirm){
				this.$emit('confirm');
			}
		},
		close(){
			const beforeClose=this.beforeClose;
			this.loadingClose=true;
			Promise.resolve(beforeClose&&beforeClose()).then((prevent) => {
				if(!prevent){
					this.$emit('close');
					this.show=false;
				}
			}).finally(() => {
				this.loadingClose=false;
			});
		},
	},
	render(h):VNode{
		const {
			title,
			default:slot,
			foot,
			loading,
			'loading-but':loadingBut,
		}=this.$scopedSlots;
		return h(Popup,{
			staticClass:this.classes,
			staticStyle:{
				zIndex:this.zIndex,
			},
			props:{
				overlay:true,
				position:null,
				closeOnClick:false,
				closeOnClickOverlay:false,
				value:this.show,
				transitionAppear:this.transitionAppear,
				contentClass:this.contentClass,
				contentStyle:this.realContentStyle,
			},
			on:{
				show:() => {
					this.$emit('show');
				},
				shown:() => {
					this.$emit('shown');
				},
				hide:() => {
					this.$emit('hide');
				},
				hidden:() => {
					this.$emit('hidden');
				},
				input:(val:boolean) => {
					this.show=val;
				}
			}
		},this.show
			?[
				this.head
					?h('div',{
						staticClass:'lexmis_head'
					},title?title(undefined):this.title)
					:null,
				h('div',{
					staticClass:'lexmis_body'
				},[
					h('div',{
						staticClass:'lexmis_content'
					},slot&&slot(undefined)),
					this.loading
						?h(QInnerLoading,{
							props:{
								showing:true,
							},
							scopedSlots:{
								default:loading||(
									() => h(QSpinner,{
										staticClass:'lexmis_modal_spinner',
									})
								)
							}
						})
						:null
				]),
				this.foot
					?h('div',{
						staticClass:'lexmis_foot'
					},foot
						?foot(undefined)
						:[
							h('div',{
								staticClass:'lexmis_confirm'+
									(this.loadingConfirm?' lexmis--loading':''),
								on:{
									click:this.confirm
								}
							},this.loadingConfirm
								?loadingBut
									?loadingBut(undefined)
									:[
										h(QSpinner,{
											staticClass:'lexmis_modal_spinner',
										})
									]
								:this.confirmText),
							this.closable
								?h('div',{
									staticClass:'lexmis_close',
									on:{
										click:this.close
									}
								},this.loadingClose
									?loadingBut
										?loadingBut(undefined)
										:[
											h(QSpinner,{
												staticClass:'lexmis_modal_spinner',
											})
										]
									:this.closeText)
								:null
						]
					)
					:null
			]
			:null
		);
	}
});
